#pragma once

#include <vector>
#include <string>
#include "../libs/easylog.h"
#include "../database.hpp"
#include "../except.hpp"
#include "../util.hpp"
#include "record.hpp"

namespace pharmacy_server
{
    class SalesRecordModel
    {
    public:
        static SalesRecordModel& instance()
        {
            static SalesRecordModel inst;
            return inst;
        }

        SalesRecordModel(const SalesRecordModel&) = delete;
        SalesRecordModel operator=(const SalesRecordModel&) = delete;

    private:
        SalesRecordModel()
        {
            try
            {
                easymysql::result res = easymysql::executer(database::instance())(R"(
SELECT username, medicine_name, quantity, action, sale_date FROM sales_records
                    )");

                SalesRecord::tuple_of_record line;
                while (res.get<SalesRecord::tuple_of_record>(&line))
                {
                    _salesrecords.push_back(new SalesRecord(line));
                }
            }
            catch (const easymysql::except& e)
            {
                easylog::error("query sales records failed exception: {}", e.what());
                throw model_except("query sales records failed exception: " + std::string(e.what()));
            }
        }
    public:

        ~SalesRecordModel()
        {
            for (auto* record : _salesrecords)
                delete record;
        }

        std::vector<SalesRecord*> query_sales_records(const std::string& medicine_name, const std::string& username, const std::string& start_date, const std::string& end_date)
        {
            std::vector<SalesRecord*> records;

            for (auto* record : _salesrecords)
            {
                if (record->sale_date >= start_date
                 && record->sale_date <= end_date
                 && record->medicine_name == medicine_name
                 && (username.empty() || (!username.empty() && username == record->username)))
                {
                    records.push_back(record);
                }
            }
            return records;
        }

        void add_sales_record(const std::string& username, const std::string& medicine_name, int quantity, const std::string& action)
        {
            try
            {
                easymysql::executer(database::instance())(R"(
INSERT INTO sales_records (username, medicine_name, quantity, action) VALUES ('{}', '{}', {}, '{}')
                    )", username, medicine_name, quantity, action);

                _salesrecords.push_back(new SalesRecord(username, medicine_name, quantity, action, time_util::time2str(time_util::now())));
            }
            catch (const easymysql::except& e)
            {
                easylog::error("add sales record failed exception: {}", e.what());
                throw model_except("add sales record failed exception: " + std::string(e.what()));
            }
        }

    private:
        std::vector<SalesRecord*> _salesrecords;
    };
}